// 咨询管理业务
let errinfo = require('../errinfo.js');
let responseJsonUtils = require('../utils/responseJsonUtils.js');
let mongoose = require('mongoose');
let _ = require('underscore');
let config = require('config');
let async = require('async');
let lodash = require('lodash');
let request = require('request');
let queryUtils = require('../utils/queryUtils');
let requestUtils = require('../utils/requestUtils');
let numPerPageUtils = require('../utils/numPerPageUtils');
let moneyUtils = require('../utils/money');
const amazonUtils = require('../utils/amazon');

let book = module.exports = {};

let ObjectId = mongoose.Types.ObjectId;
let Document = mongoose.Document;


/**
 * param bookId
 */
book.param = function (req, res, next, bookId) {
    Book.findOne({
        _id: new ObjectId(bookId)
    }).exec(function (err, bookResult) {
        if (err) {
            next(responseJsonUtils.json(errinfo.mongodb.internalError));
            return;
        }
        req.book = bookResult;
        next();
    });
};

/**
 * check delete
 */
book.checkDelete = function (req, res, next) {
    if (req.book.isDelete) {
        // activity not exist
        next(responseJsonUtils.json(errinfo.book.isDeleted, 404));
        return;
    }
    next();
};

/**
 * check book exist
 */
book.checkExist = function (req, res, next) {
    if (!req.book) {
        // book not exist
        next(responseJsonUtils.json(errinfo.book.notExist, 404));
        return;
    }
    next();
};

/**
 * add book
 */
//  check input
book.addCheckInput = function (req, res, next) {
    let body = req.body;

    if (typeof body.title === 'undefined') {
        next(responseJsonUtils.json(errinfo.book.titleEmpty, 403));
        return;
    }
    if (typeof body.isbn10 === 'undefined' && typeof body.isbn13 === 'undefined') {
        next(responseJsonUtils.json(errinfo.book.isbnEmpty, 403));
        return;
    }

    next();
};
// check exist and add
book.add = function (req, res, next) {

    let body = req.body;

    let condition = [];
    if (body.isbn10) {
        condition.push({
            isbn10: body.isbn10,
            isDelete: false,
        });
    }
    if (body.isbn13) {
        condition.push({
            isbn13: body.isbn13,
            isDelete: false,
        });
    }
    Book.findOrCreate({
        $or: condition
    }, body, function (err, bookResult, isCreate) {
        if (err) {
            next(responseJsonUtils.json(errinfo.mongodb.internalError));
            return;
        }
        if (!isCreate) {
            next(responseJsonUtils.json(errinfo.book.isbnExist, 403));
            return;
        }
        req.book = bookResult;
        next();
    });
};
// add suc
book.addSuc = function (req, res, next) {
    res.status(200).json(req.book.toJSON());
};

/**
 * delete book
 */
book.deleteSuc = function (req, res, next) {

    req.book.update({
        isDelete: true,
        deleteTime: new Date(),
        deleteUser: req.session.user
    }, function (err, bookResult) {
        if (err) {
            next(responseJsonUtils.json(errinfo.mongodb.internalError));
            return;
        }
        // redirect to all book
        // res.redirect('/book');
        res.status(200).json(req.book.toJSON());
    });
};


/**
 * update book
 */
// check book duplicate
book.updateCheckIsbn10Duplicate = function (req, res, next) {

    let originalIsbn10 = req.book.isbn10;


    let newIsbn10 = req.body.isbn10;


    if (typeof newIsbn10 === 'undefined') {
        // don't update name
        next();
        return;
    }
    if (originalIsbn10 === newIsbn10) {
        // same isbn, don't update isbn
        next();
        return;
    }
    // name not same,check new name exist

    Book.findOne({
        name: newIsbn10,
        isDelete: false
    }, function (err, bookResult) {
        if (err) {
            next(responseJsonUtils.json(errinfo.mongodb.internalError, err));
            return;
        }
        if (bookResult) {
            next(responseJsonUtils.json(errinfo.book.isbn10Duplicate, 409));
            return;
        }
        next();
    });
};
// check book isbn13 duplicate
book.updateCheckIsbn13Duplicate = function (req, res, next) {

    let originalIsbn13 = req.book.isbn13;


    let newIsbn13 = req.body.isbn13;


    if (typeof newIsbn13 === 'undefined') {
        // don't update name
        next();
        return;
    }
    if (originalIsbn13 === newIsbn13) {
        // same isbn, don't update isbn
        next();
        return;
    }
    // name not same,check new name exist

    Book.findOne({
        name: newIsbn13,
        isDelete: false
    }, function (err, bookResult) {
        if (err) {
            next(responseJsonUtils.json(errinfo.mongodb.internalError, err));
            return;
        }
        if (bookResult) {
            next(responseJsonUtils.json(errinfo.book.isbn13Duplicate, 409));
            return;
        }
        next();
    });
};
// update
book.update = function (req, res, next) {

    Object.assign(req.book, req.body, {
        updateTime: new Date(),
        updateUser: req.session.user
    });

    req.book.save(function (err, bookResult) {
        if (err) {
            next(responseJsonUtils.json(errinfo.mongodb.internalError, err));
            return;
        }
        req.book = bookResult;
        next();
    });
};
// update suc
book.updateSuc = function (req, res, next) {
    res.status(200).json(req.book.toJSON());
};

/**
 * get one book
 */
// get suc
book.getSuc = function (req, res, next) {
    if (req.book) {
        res.status(200).json(req.book.toJSON());
    } else {
        res.status(200).end();
    }
};

/**
 *
 */
book.getByIsbnFromDB = function (req, res, next) {
    Book.findOne({$or: [{isbn10: req.params.isbn}, {isbn13: req.params.isbn}]},
        function (err, bookResult) {
            if (err) {
                // save book err
                next();
                return;
            }
            if (bookResult) {
                req.book = bookResult;
                req.exist = true;
            }
            next();
        });
};
// get book from douban
book.getByIsbnFromDouban = function (req, res, next) {
    if (req.book) {
        // book exist
        next();
        return;
    }
    request.get({
        url: `https://api.douban.com/v2/book/isbn/${req.params.isbn}`,
    }, function (err, response) {
        if (err) {
            next();
            return;
        }
        if (response && response.body) {
            let result = JSON.parse(response.body);
            if (result.msg || result.code) {
                // error occur
                next();
                return;
            }
            req.book = JSON.parse(response.body);
        }

        next();
    });
};
// get book from amazon
book.getByIsbnFromAmazon = function (req, res, next) {
    if (req.book) {
        // book exist
        next();
        return;
    }

    return amazonUtils.queryBook(req.params.isbn)
        .then(function (res) {
            req.book = res;
            next();
        })
        .catch(function (err) {
            // 亚马逊请求出错
            next();
            // next(responseJsonUtils.json(errinfo.mongodb.internalError, err));
        });
};
// save book
book.getByIsbnSaveBook = function (req, res, next) {
    if (req.exist) {
        // book exist
        next();
        return;
    }
    if (!req.book) {
        // 没有从网络查询到该书籍
        next();
        return;
    }
    // book not exist
    Book.create(req.book, function (err, bookResult) {
        if (err) {
            // save book err
            next();
            return;
        }
        req.book = bookResult;
        next();
    });
};
// suc
book.getByIsbnSuc = function (req, res, next) {
    if (req.book) {
        let result;
        if (req.book instanceof Document) {
            result = req.book.toJSON();
        } else {
            result = req.book;
        }

        if (lodash.isString(result.price)) {
            result.price = result.price.replace(/[^\d.]/g, '');
            if (result.price === '') {
                result.price = 0;
            } else {
                result.price = moneyUtils.string2Float(result.price);
            }
        }

        // 厘
        result.priceInCenti = moneyUtils.getMoney(result.price);
        res.status(200).json({
            exist: req.exist,
            book: result
        });
    } else {
        res.status(404).json(errinfo.book.bookNotFound.msg);
    }
};
/**
 * book list
 */
// page info
book.page = function (req, res, next) {
    req.books = req.books || {};
    requestUtils.page(req, req.books);
    next();
};

function listCondition(req, query) {
    // title
    queryUtils.text(req, query);
    // delete
    queryUtils.delete(req, query);
    // isbn10
    queryUtils.isbn10(req, query);
    // isbn13
    queryUtils.isbn13(req, query);
}

// book count
book.calcCount = function (req, res, next) {
    let query = Book.find();

    listCondition(req, query);

    query.count(null, function (err, count) {
        if (err) {
            next(responseJsonUtils.json(errinfo.mongodb.internalError, err));
            return;
        }
        req.books = req.books || {};
        // total count
        req.books.totalCount = count;
        // per page count
        req.books.perPageCount = numPerPageUtils.book;
        // page count
        req.books.pageCount = Math.ceil(count / numPerPageUtils.book);

        next();
    });
};
// list
book.list = function (req, res, next) {

    let query = Book.find();
    query.sort('-titlePinyin.fullName.0'); // sort by createTime desc

    listCondition(req, query);

    // skip pre count
    query.skip(numPerPageUtils.book * (req.pageNo - 1));

    query.limit(numPerPageUtils.book)
        .lean()
        .exec(function (err, bookResults) {
            if (err) {
                next(responseJsonUtils.json(errinfo.mongodb.internalError));
                return;
            }
            // 将价格从字符串转换成 float
            bookResults.forEach(function (book) {
                book.price = moneyUtils.string2Float(book.price);
            });
            req.books.data = bookResults;

            // per page count
            req.books.perPageCount = numPerPageUtils.book;
            // check whether reaching the last one
            if (bookResults.length >= numPerPageUtils.book) {
                req.books.isLast = false;
            } else {
                req.books.isLast = true;
            }
            next();
        });
};

// list suc
book.listSuc = function (req, res, next) {
    res.status(200).json(req.books);
};

/**
 * list name,用于书籍名字的模糊
 */
function listNamesCondition(req, query) {
    // title
    queryUtils.text(req, query);
}

book.listNames = function (req, res, next) {
    let query = Book.find();
    query.sort('-titlePinyin.fullName.0'); // sort by createTime desc

    listNamesCondition(req, query);

    query.limit(numPerPageUtils.bookName)
        .lean()
        .select('title')
        .exec(function (err, bookResults) {
            if (err) {
                next(responseJsonUtils.json(errinfo.mongodb.internalError));
                return;
            }
            // req.books = req.books || [];
            req.books = bookResults;
            // per page count
            // check whether reaching the last one
            next();
        });
};

book.listNamesSuc = function (req, res, next) {
    res.status(200).json({
        books: req.books
    });
};

/**
 * list names from net
 */
book.listNamesFromNet = function (req, res, next) {
    if (!req.query.q) {
        next();
        return;
    }
    let url = `https://api.douban.com/v2/book/search?q=${req.query.q}`;
    if (req.query.count) {
        url = `${url}&count=${req.query.count}`;
    }
    request.get({url: url}, function (err, response) {
        if (err) {
            next();
            return;
        }
        if (response && response.body) {
            let result = JSON.parse(response.body);
            if (result.msg || result.code) {
                // error occur
                next(responseJsonUtils.json(errinfo.book.bookNotFound, 404));
                return;
            }
            req.books = JSON.parse(response.body);
        }

        next();
    });
};

book.listNamesFromNetSuc = function (req, res, next) {
    res.status(200).json({
        books: req.books
    });
};



